package org.karticks.funstuff;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class TwitterGoogleMashup
{
	private static String SCREEN_NAME_TYPE = "screen_name";
	private static String ID_TYPE = "id";
	public static void main(String[] args)
	{
		try
		{
			// first argument is your twitter screen name i.e. the twitter username
			// that you are using to map your friends
			String twitterScreenName = args[0];
			
			// the second argument is your Google Maps API key
			String mapsAPIKey = args[1];
			
			// the beginning of the URL for the Google Static Maps API
			String url = "http://maps.google.com/staticmap?";
			
			// get your own location from Twitter using your screen name
			String location = getLocation(twitterScreenName, SCREEN_NAME_TYPE);
			String geocode = "";
			
			// now geocode it ...
			if (location.startsWith("iPhone:"))
			{
				geocode = getIPhoneGeocode(location);
			}
			else
			{
				geocode = getGeocodeCoordinates(location, mapsAPIKey);
				
				geocode = getGoogleGeocode(geocode);
			}
			
			// center the map around your location
			url += "center=";
			url += geocode;
			
			// the first marker is your location and the color is set to black
			// and it will contain the letter "i" - which represents you :-)
			String markers = "&markers=";
			geocode += ",blacki|";
			
			markers += geocode;
			
			// now get your twitter friends
			List<String> friendIDs = getFriends(twitterScreenName);
			
			// for each friend id in the friend list, get the locatio of that friend
			for (String id : friendIDs)
			{
				// get the location from Twitter using the friend id
				location = getLocation(id, ID_TYPE);
				
				// if there is a non-empty location then geocode it ...
				if ((location != null) && (location.length() > 0))
				{
					geocode = "";
					if (location.startsWith("iPhone:"))
					{
						geocode = getIPhoneGeocode(location);
					}
					else
					{
						geocode = getGeocodeCoordinates(location, mapsAPIKey);
						
						geocode = getGoogleGeocode(geocode);
					}
					
					// mark your friends with a tiny red marker
					markers += geocode + ",tinyred|";
				}
			}
			
			markers = markers.substring(0, markers.length() - 1);
			
			url += "&zoom=0";
			
			// maximum size allowed by Google Static Maps
			url += "&size=640x640";
			
			url += markers;
			
			url += "&key=";
			url += mapsAPIKey;
			
			url += "&sensor=false";
			
			// All done - now print out the URL and use it ...
			System.out.println("Twitter - Google Maps Mashup URL : ");
			System.out.println(url + ".");
		}
		catch (Throwable t)
		{
			System.out.println("Caught an exception. Error message : " + t.getMessage());
			t.printStackTrace();
		}
	}
	
	private static List<String> getFriends(String twitterScreenName) throws IOException
	{
		String urlString = "http://twitter.com/friends/ids.xml?screen_name=" + twitterScreenName;
		
		String content = readURLContent(urlString);
		
		System.out.println("============================================ Friend ids (raw text) ============================================");
		System.out.println(content);
		System.out.println("===============================================================================================================");
		
		List<String> idList = new ArrayList<String>();
		
		int index1 = content.lastIndexOf("<id>");
		
		int index2 = content.lastIndexOf("</id>");
		
		while (index1 > 0)
		{
			String line = content.substring(index1, index2);
			
			int index = line.indexOf(">");
			
			String id = line.substring(index + 1);
			
			idList.add(id);
			
			content = content.substring(0, index1);
			
			index1 = content.lastIndexOf("<id>");
			
			index2 = content.lastIndexOf("</id>");
		}
		
		return idList;
	}
	
	private static String getLocation(String identity, String type) throws IOException
	{
		String urlString = "http://twitter.com/users/show.xml?";
		urlString += type;
		urlString += "=";
		urlString += identity;
				
		String content = readURLContent(urlString);
		
		System.out.println("================================================== User Info ==================================================");
		System.out.println("URL : " + urlString + ".");
		System.out.println(content);
		System.out.println("===============================================================================================================");
		
		int index1 = content.indexOf("<location>");
		int index2 = content.indexOf("</location>");
		
		String location = content.substring(index1, index2);
		
		int index = location.indexOf(">");
		
		location = location.substring(index + 1);
		
		return location;
	}
	
	private static String getGeocodeCoordinates(String location, String mapsAPIKey) throws IOException
	{
		String escapedLocation = location.replace(' ', '+');
		String urlString = "http://maps.google.com/maps/geo?q=" + escapedLocation + "&output=xml&oe=utf8&sensor=false&key=" + mapsAPIKey;
		
		String content = readURLContent(urlString);
		
		System.out.println("================================================ Geocode Info =================================================");
		System.out.println("URL : " + urlString + ".");
		System.out.println(content);
		System.out.println("===============================================================================================================");
		
		int index1 = content.indexOf("<coordinates>");
		int index2 = content.indexOf("</coordinates>");
		
		String line = content.substring(index1, index2);
		
		int index = line.indexOf('>');
		
		String coordinates = line.substring(index + 1);
		
		// remove accuracy information
		index = coordinates.lastIndexOf(',');
		coordinates = coordinates.substring(0, index);
		
		return coordinates;
	}
	
	private static String getIPhoneGeocode(String location)
	{
		String geocode = location.replace("iPhone:", "");
		geocode = geocode.trim();
		
		int index = geocode.indexOf(",");
		String lat = geocode.substring(0, index);
		String lon = geocode.substring(index + 1);
		
		geocode = lat.trim() + "," + lon.trim();
		
		return geocode;
	}
	
	// longitude and latitude are interchanged !!
	private static String getGoogleGeocode(String location)
	{
		String geocode = location;
		
		int index = geocode.indexOf(",");
		String lon = geocode.substring(0, index);
		String lat = geocode.substring(index + 1);
		
		geocode = lat.trim() + "," + lon.trim();
		
		return geocode;
	}
	
	private static String readURLContent(String urlString) throws IOException
	{
		URL url = new URL(urlString);
		
		InputStream is = (InputStream) url.getContent();

		BufferedInputStream bis = new BufferedInputStream(is);
		
		byte[] buffer = new byte[1024];
		int numRead = 0;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		while (true)
		{
			numRead = bis.read(buffer, 0, buffer.length);
			
			if (numRead != -1)
			{
				baos.write(buffer, 0, numRead);
			}
			else
			{
				break;
			}
		}
		
		baos.flush();
		
		String text = baos.toString();
		
		baos.close();
		
		return text;
	}
}
